
#ifndef OCCVIEW_H
#define OCCVIEW_H

// Qt Include
#include <QRegularExpression>
#include <QMatrix4x4>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QKeyEvent>
#include <QApplication>
#include <qmessagebox.h>
#include <QPaintEngine>
#include <QPaintEvent>
#include <qwidget.h>
#include <QOpenGLWidget>
#include <QStack>


// OpenCascade Include
#include <AIS_AnimationCamera.hxx>
#include "AIS_TextLabel.hxx"
#include "Geom_CartesianPoint.hxx"
#include "TopLoc_Location.hxx"
#include "AIS_Point.hxx"
#include "Geom_Axis2Placement.hxx"
#include "BRepBuilderAPI_Transform.hxx"
#include "Geom_Line.hxx"
#include "BRepBndLib.hxx"
#include <BRepBuilderAPI_Sewing.hxx>
#include "TopTools_HSequenceOfShape.hxx"
#include <Geom_BezierCurve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <Geom_Circle.hxx>
#include <AIS_InteractiveContext.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <V3d_View.hxx>
#include <Aspect_Handle.hxx>
#include <Aspect_DisplayConnection.hxx>
#include <Graphic3d_GraphicDriver.hxx>
#include <IGESControl_Reader.hxx>
#include <StlAPI_Reader.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrimAPI_MakeCone.hxx>
#include <BRepPrimAPI_MakeTorus.hxx>
#include <gp_Circ.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <AIS_Shape.hxx>
#include <gp_Pnt.hxx>
#include <gp_Ax1.hxx>
#include <gp_Dir.hxx>
#include <GProp_GProps.hxx>
#include <BRepGProp.hxx>
#include <Standard_Real.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <GCPnts_UniformAbscissa.hxx>
#include <GCPnts_AbscissaPoint.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <AIS_ViewCube.hxx>
#include <Geom_Curve.hxx>
#include <GeomAPI_IntCS.hxx>
#include <STEPControl_Reader.hxx>
#include <qfiledialog.h>
#include <Geom_Line.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <StlAPI_Writer.hxx>


#ifdef _WIN32
#include <WNT_Window.hxx>
#else
#undef None
#include <Xw_Window.hxx>
#endif

// Assimp Inculde
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <assimp/ai_assert.h>
#include <assimp/vector3.h>
#include <assimp/Exporter.hpp>


using namespace Assimp;
using namespace std;//使用命名空间

//---模型加载工具类
class CModel : public AIS_Shape
{
    DEFINE_STANDARD_RTTIEXT(CModel, AIS_Shape)
public:
    //构造函数
    CModel(const TopoDS_Shape& _shape = TopoDS_Shape());

    // 构造函数，加载文件
    CModel(const QString _filepath);

    // 模型类型
    enum MODEL_TYPE
    {
        MODEL_COMPONENT = 1,    // 部件
        MODEL_COMP_GROUP = 2,   // 部件组
    };

    // 设置模型名称
    // brief m_set_model_name
    // param _name 模型名称
    inline void m_set_model_name(QString _name){m_model_name = _name;}

    // 获取模型的名称
    // brief m_get_model_name
    // return 模型名称
    inline QString m_get_model_name(){return m_model_name;}

    // 使用QMatrix4x4矩阵设置模型位姿
    // brief m_set_pose_by_matrix
    // param _matrix 齐次矩阵
    void m_set_pose_by_matrix(QMatrix4x4 _matrix);

    // 设置模型类型
    inline void m_set_model_type(MODEL_TYPE _type){m_model_type = _type;}

    // 获取模型类型
    inline MODEL_TYPE m_get_model_type(){return m_model_type;}

    // 获取整个模型的AABB包围盒，包括子模型
    Bnd_Box m_get_full_aabb();

    // 导出模型
    // brief m_export_model
    // param _filename 文件名字
    // param _format 文件格式
    // return
    static bool m_export_model(QString _filename , const char *_format_id,Handle(AIS_InteractiveContext) _context);

private:
    // 模型名称
    QString m_model_name;

    // 模型种类
    MODEL_TYPE m_model_type;

    // 处理所有ASSIMP节点
    // brief m_process_nodes
    // param _node 节点
    // param _scene 场景
    // param _is_root 是否为根节点
    void m_process_nodes(const aiNode *_node, const aiScene *_scene, bool _is_root);

    // 模型材质转换，由ASSIMP转成OCC表示方式
    Graphic3d_MaterialAspect m_material_transfer(aiMaterial *_material);

};

DEFINE_STANDARD_HANDLE(CModel, AIS_Shape)// 定义智能指针类型


//-------三维显示窗口
class OccView : public QWidget
{
    Q_OBJECT
public:
    explicit OccView(QWidget *parent = nullptr);
    ~OccView();
    Handle(AIS_InteractiveContext) m_get_context(){return m_context;}// 获取三维环境交互对象
    Handle(V3d_View)  m_get_view(){return m_view;}// 获取三维显示界面
    void m_initialize_context();//初始化交互环境
    void save();//保存三维坐标的方法
    void loadFileModel();//加载模型文件
    void clearModels();//清空导入的模型
    void undo();//撤销功能
    Standard_Integer numPoints = 100; // 希望生成的点的数量 默认100

private:
    Handle(AIS_InteractiveContext) m_context;//交互式上下文能够管理一个或多个查看器(viewer)中的图形行为和交互式对象的选择
    Handle(V3d_Viewer) m_viewer;//定义查看器(viewer)类型对象上的服务
    Handle(V3d_View) m_view; //创建一个视图
    Handle(Graphic3d_GraphicDriver)  m_graphic_driver; //创建3d接口定义图形驱动程序
    Handle(TopTools_HSequenceOfShape) aHSequenceOfShape;//当前选择的容器
    void showGraphic3d();//显示3维视图
    void showModelOrigin(TopoDS_Shape shape);//显示模型原点在世界坐标系中的位置
    vector<vector<gp_Pnt>> allPoint;//存储当前直线的坐标
    void multiselecteShape();//多项选择
    void selecteShape();//单选择
    void saveFaceAsStl(const TopoDS_Face& face);//保存stl格式
    void sava3DPoint(vector<vector<gp_Pnt>> linePoint);//保存坐标
    void showCurrentSelect();//展示当前的选择
    QStack<Handle(TopTools_HSequenceOfShape)> *undoStack;//当前选择的容器栈
    QStack<Handle(AIS_Selection)> *selectionStack;//当前选择
    Handle(AIS_Selection) currentSelection;//当前选择的形状
    Handle(AIS_InteractiveContext) myContext;//返回交互上下文
    void AddSelect(const Handle(SelectMgr_EntityOwner)& theObject);//增加选择
    void SaveCurrentSelection();//保存当前选择
    void RestorePreviousSelection();//返回上一个选择
    QStack<vector<Handle(SelectMgr_EntityOwner)>> mySelectionHistory;//历史选择
    void CyclicViewChange();//切换视角


protected:
    virtual void paintEvent(QPaintEvent *) override;//覆写绘图事件
    virtual void resizeEvent(QResizeEvent *) override; //覆写窗口尺寸变化事件
    virtual void mousePressEvent(QMouseEvent *event) override;//覆写鼠标按键按下事件
    virtual void mouseReleaseEvent(QMouseEvent *event) override;//覆写鼠标按键释放事件
    virtual void mouseMoveEvent(QMouseEvent *event) override;//覆写鼠标移动事件
    virtual void wheelEvent(QWheelEvent *event) override;//覆写鼠标滚轮事件
    virtual void keyPressEvent(QKeyEvent *event)override;//键盘按下事件
    virtual void onMouseWheel(const int theFlags, const int theDelta, const QPoint thePoint);//缩放

    QPaintEngine *paintEngine() const override; // 返回窗口的绘制引擎

private:
    Standard_Integer m_x_max;    //记录鼠标平移坐标X
    Standard_Integer m_y_max;    //记录鼠标平移坐标Y

signals:

public slots:
};

#endif // OCCVIEW_H
